
import screenlets
import gobject
import threading
import twitter
import urllib
import gtk

import traceback

# parse_qsl moved to urlparse module in v2.6
try:
  from urlparse import parse_qsl
except:
  from cgi import parse_qsl

import oauth2 as oauth

REQUEST_TOKEN_URL = 'https://api.twitter.com/oauth/request_token'
ACCESS_TOKEN_URL  = 'https://api.twitter.com/oauth/access_token'
AUTHORIZATION_URL = 'https://api.twitter.com/oauth/authorize'
SIGNIN_URL        = 'https://api.twitter.com/oauth/authenticate'

consumer_key    = "Hw59xrDzlSddJgpEMAoxg"
consumer_secret = "Te8dRb7Lk3MfIkJx9RdBdwRj4heELLsplUhIc0RQ"

class UserInfo:
    def __init__ (self, name=None, screen_name=None, iconPixbuf=None):
        self.name = name
        self.screen_name = screen_name
        self.iconPixbuf = iconPixbuf

class Timeline:
    statuses = []
    users = {}

    def __init__ (self, statuses=None, users=None):
        if statuses: self.statuses = list(statuses)
        if users: self.users = dict(users)
            
class TwitterResult:
    SUCCESS		= 1
    ERROR		= 2

class TwitterUpdateMethod:
    PUBLIC = 1
    FRIENDS = 2

class TwitterBackend (gobject.GObject):
    """The backend class which performs getting Twitter statuses"""

    statuses = []
    users = {}
    icon_cache = {}
    handler_ids = []

    __api = None

#    request_token = None
    oauth_consumer = None

    started = False

    __lock = threading.Lock()

    def __init__ (self, screenlet, update_method):
        print "TwitterBackend.__init__"
        gobject.GObject.__init__(self)
        # properties
        self.screenlet		= screenlet		# assigned TwitterScreenlet
        self.getting		= False			# not getting yet
        self.error					= ''		# human-readable error message
        self.options		= []				# ???additonal ptions for backend
        self.update_method      = update_method

        self.__api = self.get_twitter_api(self.screenlet.access_key, self.screenlet.access_secret)

    def open_access_url(self):

	print '*** Requesting temp token from Twitter ***'

	signature_method_hmac_sha1 = oauth.SignatureMethod_HMAC_SHA1()
	self.oauth_consumer             = oauth.Consumer(key=consumer_key, secret=consumer_secret)
	oauth_client               = oauth.Client(self.oauth_consumer)

	resp, content = oauth_client.request(REQUEST_TOKEN_URL, 'GET')

	if resp['status'] != '200':
	  print 'Invalid respond from Twitter requesting temp token: %s' % resp['status']
	else:
	  request_token = dict(parse_qsl(content))

#	  print resp
#	  print content

#	  print "REQUEST TOKEN: ", request_token
#	  print "REQUEST OAUTH TOKEN: ", request_token['oauth_token']
#	  print "REQUEST OAUTH TOKEN SECRET: ", request_token['oauth_token_secret']

	  print ''
	  print 'Please visit this Twitter page and retrieve the pincode to be used'
	  print 'in the next step to obtaining an Authentication Token:'
	  print ''
#		  print '%s?oauth_token=%s' % (AUTHORIZATION_URL, self.request_token['oauth_token'])
	  print ''

	  stttt = AUTHORIZATION_URL + '?oauth_token=' + request_token['oauth_token']
	  print stttt
	  print ''

	  return [stttt, request_token]

    def get_access_key(self, pincode, request_key, request_secret):

	  print "*** Generating and signing request for an access token ***"
	  
#		  print "PINCODE: ", pincode

#		  if self.request_token is None:
#			print "REQUEST TOKEN not available yet!!!"
#			return None

#		  print "REQUEST TOKEN: ", self.request_token
#		  print "REQUEST OAUTH TOKEN: ", self.request_token['oauth_token']
#		  print "REQUEST OAUTH TOKEN SECRET: ", self.request_token['oauth_token_secret']

	  if self.oauth_consumer is None:
		signature_method_hmac_sha1 = oauth.SignatureMethod_HMAC_SHA1()
		self.oauth_consumer = oauth.Consumer(key=consumer_key, secret=consumer_secret)

	  token = oauth.Token(request_key, request_secret)
	  token.set_verifier(pincode.strip())

	  oauth_client  = oauth.Client(self.oauth_consumer, token)
	  resp, content = oauth_client.request(ACCESS_TOKEN_URL, method='POST', body='oauth_verifier=%s' % pincode)
	  access_token  = dict(parse_qsl(content))

	  if resp['status'] != '200':
		print 'The request for a Token did not succeed: %s' % resp['status']
#		print access_token
	  else:
		print 'Your Twitter Access Token key: %s' % access_token['oauth_token']
		print '          Access Token secret: %s' % access_token['oauth_token_secret']
		print ''
		return access_token

	  return None



    def get_twitter_api(self, key = None, secret= None):

#	print "*** GET API ***"
#	print "ACCESS_TOKEN (KEY)", key
#	print "ACCESS_TOKEN_SECRET (SECRET)", secret

#	print consumer_key, consumer_secret

        api = twitter.Api(consumer_key=consumer_key, consumer_secret=consumer_secret, access_token_key=key,
                            access_token_secret=secret, input_encoding="UTF-8")

	print "API OK", api
        # Mail to Alex...
        api.SetUserAgent('TwitterScreenlet')
        
        #api.SetCacheTimeout(0)
        return api

    def get_timeline_start(self):
        if self.getting: return        
        threading.Thread(target=self.__get).start()

    def post_message_start(self, text):
        threading.Thread(target=self.__post, args=(text,)).start()

    def __get (self):
	""" """
	self.getting = True
	result = TwitterResult.SUCCESS

	try:
		self.__lock.acquire()
		self.__get_timeline()
	except:
#                traceback.print_exc()
		result = TwitterResult.ERROR
	finally:
		self.__lock.release()

	gobject.idle_add(self.screenlet.on_get_timeline, Timeline(self.statuses, self.users), result)
	self.getting = False

    def __post (self, text):
        """ post message to server"""
        try:
		self.__lock.acquire()
#		print "U --- " + str(len(unicode(text))) + ": '" + text + "'"
#		print "T --- " + str(len(text)) + ": '" + text + "'"
		#            self.__api.PostUpdate(unicode(text))
		self.__api.PostUpdate(text)
		gobject.idle_add(self.screenlet.on_post_message, TwitterResult.SUCCESS)
	except:
		gobject.idle_add(self.screenlet.on_post_message, TwitterResult.ERROR)
        finally:
		self.__lock.release()
    
    def __get_timeline(self):
        """ get twitter timeline data"""

	howmany = min(100, int(self.screenlet.num_of_statuses))

	print "trying to get some %d timelines..." % howmany

        try:

		if self.update_method == TwitterUpdateMethod.FRIENDS:
			self.statuses = self.__api.GetFriendsTimeline(count=howmany)
		else:
			self.statuses = self.__api.GetPublicTimeline()

	except twitter.TwitterError as message:
		self.screenlet.__notifier.notify("Twitter.com says: \"" + str(message) + "\"")
#                traceback.print_exc()
	except:
		self.screenlet.__notifier.notify("Communication with Twitter.com failed.")
#                traceback.print_exc()

        new_icon_cache = {}
#	user_dict = {}

	if(len(self.users) > 200):
		self.users = {}

        user_dict = self.users

	print "working on usericons..."
        for status in self.statuses:
	    if howmany == 0: break
	    howmany -= 1
#	    print status.GetUser().GetScreenName(), user_dict.has_key(status.GetUser().GetId())
            if not user_dict.has_key(status.GetUser().GetId()):

                user_name = status.GetUser().GetName()
                screen_name = status.GetUser().GetScreenName()

                # get Profile Image
                try:
                    icon_url = status.GetUser().GetProfileImageUrl()
                    if self.icon_cache.has_key(icon_url):
                        icon_pixbuf = icon_cache[icon_url]
                    elif new_icon_cache.has_key(icon_url):
                        icon_pixbuf = new_icon_cache[icon_url]
                    else:
                        icon_path, headers = urllib.urlretrieve(urllib.quote(icon_url.encode("utf-8"), ':/'))
                        icon_pixbuf = gtk.gdk.pixbuf_new_from_file(icon_path)

                    new_icon_cache[icon_url] = icon_pixbuf
                except:

                    #traceback.print_exc()
                    print 'Failed to get icon pixbuf: ', icon_url, ' ignoring...'
                    icon_pixbuf = None

                user_dict[status.GetUser().GetId()] = UserInfo(user_name, screen_name, icon_pixbuf)

#        self.users = user_dict

        icon_cache = new_icon_cache
        urllib.urlcleanup()

	print "finished :)"

    def set_update_method(self, update_method):
#        self.__lock.acquire()
#        if update_method == TwitterUpdateMethod.FRIENDS:
            self.update_method = update_method
#        else:
 #           self.__update_method = self.__api.GetPublicTimeline
 #       self.__lock.release()
